package com.vincent.template.utils;

import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Pattern;

/**
 * @Author Vincent Wang
 * @Date 2020/9/2 18:06
 */
public class DateUtil {

    private static final int LENGTH_YYYY_MM_DD = 10;
    private static final Pattern PATTERN_YYYY_MM_DD = Pattern.compile("((\\d{2}(([02468][048])|([13579][26]))[\\-]((((0?[13578])|(1[02]))[\\-]((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-]((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-]((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-]((((0?[13578])|(1[02]))[\\-]((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-]((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-]((0?[1-9])|(1[0-9])|(2[0-8]))))))");
    private static final Pattern PATTERN_YYYY_MM = Pattern.compile("([12]\\d{3}-(0[1-9]|1[0-2]))");
    private static final String YMD_WITH_TIME = "yyyy-MM-dd HH:mm:ss";
    private static final String YYYY_MM_DD = "yyyy-MM-dd";
    private static final String YYYY_MM = "yyyy-MM";

    private DateUtil() {
    }

    /**
     * 判断日期格式是否符合yyyy-MM（为空不检验）
     * @param required
     * @param dateStr
     * @return
     */
    public static boolean matchYM(boolean required, String dateStr) {
        if (StringUtils.isBlank(dateStr)) {
            return !required;
        }
        return PATTERN_YYYY_MM.matcher(dateStr).matches();
    }

    /**
     * 判断日期格式是否符合yyyy-MM-dd（为空不检验）
     * @param required
     * @param dateStr
     * @return
     */
    public static boolean matchYMD(boolean required, String dateStr) {
        if (StringUtils.isBlank(dateStr)) {
            return !required;
        }
        return matchYMD(dateStr);
    }

    /**
     * 判断日期格式是否符合yyyy-MM-dd
     * @param dateStr
     * @return
     */
    public static boolean matchYMD(String dateStr) {
        return StringUtils.isNotBlank(dateStr) && dateStr.length() == LENGTH_YYYY_MM_DD && PATTERN_YYYY_MM_DD.matcher(dateStr).matches();
    }

    public static String formatToYmdWithTime(Date date) {
        if (date == null) {
            return "";
        }
        return new SimpleDateFormat(YMD_WITH_TIME).format(date);
    }

    public static String formatToYmd(Date date) {
        if (date == null) {
            return "";
        }
        return new SimpleDateFormat(YYYY_MM_DD).format(date);
    }

    public static String formatToYm(Date date) {
        if (date == null) {
            return "";
        }
        return new SimpleDateFormat(YYYY_MM).format(date);
    }

    /**
     * 日期字符串yyyy-MM-dd转化为日期
     * 因为日期格式和是否能为空在进入接口的时候已经用@MatchYMD注解check过了，所以此方法只负责日期转换
     * @param dateStr
     * @return
     */
    public static Date parseToDate(String dateStr) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            return new SimpleDateFormat(YYYY_MM_DD).parse(dateStr);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 将yyyy-MM转化为日期
     * 因为日期格式和是否能为空在进入接口的时候已经用@MatchYM注解check过了，所以此方法只负责日期转换
     * @param dateStr
     * @return
     */
    public static Date parseMonthToDate(String dateStr) {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        try {
            return new SimpleDateFormat(YYYY_MM).parse(dateStr);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 获得当前时间和当天最后一刻相差的毫秒数
     * @return
     */
    public static long getMillisBetweenNowAndEndOfToday() {
        return getMillisBetweenNowAndEndOfSomeDay(0);
    }

    /**
     * 获得当前时间和某天最后一刻相差的毫秒数
     * @param offset
     * @return
     */
    public static long getMillisBetweenNowAndEndOfSomeDay(int offset) {
        long currentTimeMillis = System.currentTimeMillis();
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(currentTimeMillis);
        calendar.add(Calendar.DATE, offset);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTimeInMillis() - currentTimeMillis;
    }

}
